/**
 * Copyright [2019] [LiBo/Alex of copyright liboware@gmail.com ]
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.dess.stateful.egine.core.impl;

import com.hyts.dess.stateful.egine.core.StateMachine;
import com.hyts.dess.stateful.egine.model.StateActionModule;
import com.hyts.dess.stateful.egine.model.StateFlowModule;
import com.hyts.dess.stateful.egine.model.StatePointModule;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @project-name:dess
 * @package-name:com.hyts.dess.stateful.egine.core.impl
 * @author:LiBo/Alex
 * @create-date:2020-06-23 14:14
 * @copyright:libo-alex4java
 * @email:liboware@gmail.com
 * @description: 默认实现状态机上下文操作对象
 */
public class DefaultStateMachine implements StateMachine {


    /** 状态流转模型缓存，以 StateFlowConfigDTO.id 做为键 */
    static final Map<String, Map<String, Map<String, StateActionModule>>> FLOW_MAP = new HashMap<>();

    /**
     * 获取相关的状态流模型模块服务
     * @param stateFlowModule
     * @return
     */
    @Override
    public Map<String, Map<String, StateActionModule>> getStateFlowModule(StateFlowModule stateFlowModule) {
        // 状态流相关的module对象相关服务
        Objects.requireNonNull(stateFlowModule,"传入的状态流对象不允许为空!");
        Objects.requireNonNull(stateFlowModule.getCode(),"传入的状态流对象不允许为空!");
        // 先取缓存
        Map<String, Map<String, StateActionModule>> result = FLOW_MAP.get(stateFlowModule.getId());
        // 如果获取到相关的状态流模板的数据结果集对象
        if(Objects.nonNull(result)){
            return result;
        }
        // 建模，用空间换时间，并且缓存下来
        // 将原有list模型转换成Map，查找的时间复杂度为O(1)
        //内部防止NPE
        if (CollectionUtils.isEmpty(stateFlowModule.getStatePointModuleList())){
            return result;
        }
        result = stateFlowModule.getStatePointModuleList().parallelStream().
                filter(param->!CollectionUtils.isEmpty(param.getActionModuleList()))
                .collect(Collectors.toMap(StatePointModule::getValue, v->
                        v.getActionModuleList().parallelStream().collect(Collectors.toMap(StateActionModule::getOperatorCode, v1->v1))));
        FLOW_MAP.put(stateFlowModule.getCode(),result);
        return result;
    }

    /**
     * 删除相关的状态流对象信息配置
     * @param stateFlowModule
     * @return
     */
    @Override
    public boolean removeStateFlowModule(StateFlowModule stateFlowModule) {
        return Objects.nonNull(FLOW_MAP.remove(stateFlowModule.getCode()));
    }

    /**
     * 获取改状态下面并且
     * @param state
     * @param stateFlowModule
     * @return
     */
    @Override
    public List<StateActionModule> getActionSubjects(String state, StateFlowModule stateFlowModule) {
        Objects.requireNonNull(stateFlowModule,"传入的状态流转对象不允许为空！");
        // 获取转换好的模型，查找的时间复杂度为O(1)
        Map<String, Map<String, StateActionModule>> flowMap = getStateFlowModule(stateFlowModule);
        Map<String, StateActionModule> operators = flowMap.get(state);
        if (operators == null){
            return null;
        }
        // 遍历取出操作列表
        List<StateActionModule> operatorList = new ArrayList<>();
        for (Map.Entry<String, StateActionModule> item : operators.entrySet()) {
            operatorList.add(item.getValue());
        }
        return operatorList;
    }
}
